Skip to content

With &&

The downside with using an if statement is that we need to pull the logic up, away from the rest of the markup. While this is perfectly valid, it can make it harder to understand how a component is structured, especially in larger and more-complex components. We'd have to hop all over the place to understand what gets returned!

Fortunately, there's a way for us to embed if logic right in our JSX: using the && operator.

Here's how we'd do it:

Code Playground

function Friend({ name, isOnline }) {
return (
<li className="friend">
{isOnline && <div className="green-dot" />}
{name}
</li>
);
}

function App() {
return (
<ul className="friend-list">
<Friend name="Andrew" isOnline={false} />
<Friend name="Beatrice" isOnline={true} />
<Friend name="Chen" isOnline={true} />
</ul>
);
}

export default App;

In JavaScript, && is a control flow operator. It works quite a bit like if/else, except it's an expression instead of a statement.

To help us understand what's actually happening here, let's take a look at the exact same logic, but expressed using if/else:

function Friend({ name, isOnline }) {
let prefix;
if (isOnline) {
prefix = <div className="green-dot" />;
} else {
prefix = isOnline;
}
return (
<li className="friend">
{prefix}
{name}
</li>
);
}

The && operator is said to be a “control flow” operator because, like if/else, it will always result in one of two paths being taken.

If the left-hand value (isOnline) is falsy, the expression short-circuits, and evaluates to isOnline, which resolves to false. If that value is truthy, however, it evaluates to whatever's on the right-hand side of the operator (<div className="green-dot" />).

You can think of the && operator a bit like a nightclub bouncer. If you try to get in with a fake ID, the bouncer won't let you access the React element on the other side. If the value is truthy, though, the bouncer unhooks the velvet rope, and we're allowed to access the React element.

Illustration of a bouncer in front of velvet ropes. Behind the ropes is the code “<div className='green-dot' />”

This concept is explained in greater depth in the JavaScript primer lesson “Logical Operators” 👀.

Common gotcha: the number zero

Consider this situation:

function App() {
const shoppingList = ['avocado', 'banana', 'cinnamon'];
const numOfItems = shoppingList.length;
return (
<div>
{numOfItems && (
<ShoppingList items={shoppingList} />
)}
</div>
);
}

We have a component, ShoppingList, and it only really makes sense to render that component if we have at least 1 item in our shopping list.

If you've been using JavaScript for a while, you might know that every number in JS is truthy except 0. 0 is the only falsy number, just like how '' is the only falsy string.

Therefore, it seems to make sense to do things this way. If numOfItems has at least 1 item in it, it will be truthy, and we'll render the <ShoppingList> element. If we have 0 items, we should skip it.

But check out what happens when we actually run this setup:

Code Playground

import ShoppingList from './ShoppingList';

function App() {
const shoppingList = [];
const numOfItems = shoppingList.length;

return (
<div>
{numOfItems && (
<ShoppingList items={shoppingList} />
)}
</div>
);
}

export default App;

We wind up with 0 being rendered!

Why is this happening? We need to keep two things in mind:

  1. The && operator doesn't return true or false. It returns either the left-hand side or the right-hand side. So, when our list is empty, this expression evaluates to 0.
  2. React will render any number you give it, even zero!

React will ignore most falsy values like false or null, but it won't ignore the number zero.

In fact, let's see how React handles all of the different falsy values:

Code Playground

function App() {
return (
<ul>
<li>false: {false}</li>
<li>undefined: {undefined}</li>
<li>null: {null}</li>
<li>Empty string: {''}</li>
<li>Zero: {0}</li>
<li>NaN: {NaN}</li>
</ul>
);
}

export default App;

React will actually render the number 0. And when we think about it, this makes sense. There are lots of situations where we'd want to render this number:

function Banner({ ticketsRemaining }) {
return (
<h2>
Number of JIRA tickets left: {ticketsRemaining}.
</h2>
);
}

If ticketsRemaining is equal to 0, we want to show the number 0, not an empty space!

Solution: Always use boolean values with &&

To avoid having random 0 characters sprinkled around your application, I suggest following a “golden rule”: make sure that the left-hand side of && always evaluates to a boolean value, either true or false.

For example, we can check if the number is greater than zero:

function App() {
const shoppingList = ['avocado', 'banana', 'cinnamon'];
const numOfItems = shoppingList.length;
return (
<div>
{numOfItems > 0 && (
<ShoppingList items={shoppingList} />
)}
</div>
);
}

I really like this approach. We're being really specific with what the condition is: if we have 1 or more items in the shopping list, we should render the <ShoppingList> element. The “greater than” operator (>) will always produce a boolean value, either true or false.

We can also convert any non-boolean value to a boolean value with !!:

function App() {
const shoppingList = ['avocado', 'banana', 'cinnamon'];
const numOfItems = shoppingList.length;
return (
<div>
{!!numOfItems && (
<ShoppingList items={shoppingList} />
)}
</div>
);
}

If you're not sure what's going on here with !!, check out the JavaScript Primer lesson on Truthy and Falsy 👀.